package com.example.a05;

import org.springframework.context.support.GenericApplicationContext;


public class Application05 {
    public static void main(String[] args) {
        // GenericApplicationContext：一个干净的容器
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);
/*
    综合实现
        // ConfigurationClassPostProcessor 可识别@ComponentScan @Bean @Import @ImportResource
        context.registerBean(ConfigurationClassPostProcessor.class);
        // MapperScannerConfigurer 扫描Mybatis的Mapper接口
        context.registerBean(MapperScannerConfigurer.class,
                bd -> bd.getPropertyValues().add("basePackage", "com.example.a05.mapper"));
*/

/*
    ComponentScan运行分析
        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
        if (componentScan != null) {
            for (String s : componentScan.basePackages()) {
                System.out.println(s);
                String path = "classpath*:" + s.replace(".", "/") + "/** /*.class";
                System.out.println(path);
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                // 扫描路径下的文件
                Resource[] resources = context.getResources(path);
                // Bean名生成器
                AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                for (Resource resource : resources) {
                    MetadataReader reader = factory.getMetadataReader(resource);
//                    System.out.println("类名：" + reader.getClassMetadata().getClassName());
                    AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
//                    System.out.println("是否存在Component注解："
//                            + annotationMetadata.hasAnnotation(Component.class.getName()));
//                    System.out.println("是否存在Component派生注解："
//                            + annotationMetadata.hasMetaAnnotation(Component.class.getName()));

                    if (annotationMetadata.hasAnnotation(Component.class.getName())
                            || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
                        AbstractBeanDefinition bd = BeanDefinitionBuilder
                                .genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
                        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
                        String name = generator.generateBeanName(bd, beanFactory);
                        beanFactory.registerBeanDefinition(name, bd);
                    }
                }
            }
        }
*/

/*
    Bean运行分析
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/example/a05/Config.class"));
        Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata method : methods) {
            System.out.println(method);
            String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();

            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
            builder.setFactoryMethodOnBean(method.getMethodName(), "config");
            // 指定自动装配模式
            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
            if (!initMethod.isEmpty()) {
                builder.setInitMethodName(initMethod);
            }

            AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
            context.getDefaultListableBeanFactory().registerBeanDefinition(method.getMethodName(), beanDefinition);
        }
*/
        context.registerBean(AtBeanPostProcessor.class);    // 解析@Bean
        context.registerBean(ComponentScanPostProcessor.class); // 解析@ComponentScan
        context.registerBean(MapperPostProcessor.class);    // 解析 Mapper 接口

        // 初始化容器
        context.refresh();

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        // 销毁容器
        context.close();
    }
}
